package guiTesting;

import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.ImmutableSet;


import com.atlassian.crowd.integration.rest.entity.UserEntity;
import com.atlassian.crowd.integration.rest.service.factory.RestCrowdClientFactory;
import com.atlassian.crowd.model.authentication.CookieConfiguration;
import com.atlassian.crowd.model.authentication.UserAuthenticationContext;
import com.atlassian.crowd.model.authentication.ValidationFactor;
import com.atlassian.crowd.model.group.GroupWithAttributes;
import com.atlassian.crowd.model.group.Membership;
import com.atlassian.crowd.model.user.User;
import com.atlassian.crowd.model.user.UserWithAttributes;
import com.atlassian.crowd.search.query.entity.restriction.BooleanRestrictionImpl;
import com.atlassian.crowd.search.query.entity.restriction.MatchMode;
import com.atlassian.crowd.search.query.entity.restriction.NullRestrictionImpl;
import com.atlassian.crowd.search.query.entity.restriction.Property;
import com.atlassian.crowd.search.query.entity.restriction.PropertyImpl;
import com.atlassian.crowd.search.query.entity.restriction.TermRestriction;
import com.atlassian.crowd.search.query.entity.restriction.constants.UserTermKeys;
import com.atlassian.crowd.service.client.CrowdClient;
import com.atlassian.crowd.embedded.api.Group;
import com.atlassian.crowd.embedded.api.PasswordCredential;
import com.atlassian.crowd.embedded.api.SearchRestriction;
import com.atlassian.crowd.event.EventTokenExpiredException;
import com.atlassian.crowd.event.Events;
import com.atlassian.crowd.event.IncrementalSynchronisationNotAvailableException;
import com.atlassian.crowd.exception.ApplicationAccessDeniedException;
import com.atlassian.crowd.exception.ApplicationPermissionException;
import com.atlassian.crowd.exception.CrowdException;
import com.atlassian.crowd.exception.ExpiredCredentialException;
import com.atlassian.crowd.exception.GroupNotFoundException;
import com.atlassian.crowd.exception.InactiveAccountException;
import com.atlassian.crowd.exception.InvalidAuthenticationException;
import com.atlassian.crowd.exception.InvalidCredentialException;
import com.atlassian.crowd.exception.InvalidEmailAddressException;
import com.atlassian.crowd.exception.InvalidGroupException;
import com.atlassian.crowd.exception.InvalidTokenException;
import com.atlassian.crowd.exception.InvalidUserException;
import com.atlassian.crowd.exception.MembershipNotFoundException;
import com.atlassian.crowd.exception.OperationFailedException;
import com.atlassian.crowd.exception.UnsupportedCrowdApiException;
import com.atlassian.crowd.exception.UserNotFoundException;


public class RetrieveUserInfo{

	public int maxResults = -1;
	public int startIndex = 0;
	/*
	 * Connect to the app on Crowd.
	 */
	static String appLink = "https://code.bestbuy.com/crowd/";
	static CrowdClient conn = new RestCrowdClientFactory().newInstance(appLink,"profile-mgt","1nitialPa55");



	/*
	 * -------------------------------ACCESS USER INFORMATION FROM CROWD API----------------------
	 */


	/*
	 * Get user basic information 
	 */

	public  List<String> getUserInfo (String usN) throws UserNotFoundException, OperationFailedException, ApplicationPermissionException, InvalidAuthenticationException{

		User usr = conn.getUser(usN);
		//String userName; String firstName; String lastName; String email; 

		ArrayList<String> userInfo = new ArrayList<String>();

		// conn.testConnection();

		userInfo.add(usr.getDisplayName());
		userInfo.add(usr.getFirstName());
		userInfo.add(usr.getLastName());
		userInfo.add(usr.getEmailAddress());
		userInfo.add(usr.getName());
		return userInfo;

	}

	/*
	 * returns all names of groups which the user is a direct member 
	 */
	public List<String> getNamesOfGroupsForUser (String userName) throws UserNotFoundException, OperationFailedException, InvalidAuthenticationException, ApplicationPermissionException{
		List userGroups =conn.getNamesOfGroupsForUser(userName, startIndex, maxResults);
		return userGroups;

	}

	/*
	 * Return groups which user belong 
	 */
	public List<String> getGroupsForUser (String userName) throws UserNotFoundException, OperationFailedException, InvalidAuthenticationException, ApplicationPermissionException{
		List userGroups =conn.getGroupsForUser(userName, startIndex, maxResults);
		return userGroups;
	}

	/*
	 * Get Direct members (users)  of a Group. 
	 */

	public  List<String> getGroupUsers(String gU) throws GroupNotFoundException, OperationFailedException, InvalidAuthenticationException, ApplicationPermissionException{
		ArrayList<String> groupUsers = new ArrayList<String>();
		com.atlassian.crowd.model.group.Group gr = conn.getGroup(gU); 
		List<String> grUsers = conn.getNamesOfUsersOfGroup(gU, startIndex, maxResults);

		for (int i=0; i<grUsers.size();i++){
			groupUsers.add(grUsers.get(i));
		}
		return groupUsers ;
	}

	/*
	 * Get nested Members of a Group.  This return Users ( User Entinty)  
	 */
	public List<User> getNestedUsersOfGroup (String groupName, int startIndex, int maxResults) throws GroupNotFoundException, OperationFailedException, InvalidAuthenticationException, ApplicationPermissionException{
		List groupNestedUsers = conn.getNestedUsersOfGroup(groupName, startIndex, maxResults);
		return groupNestedUsers;
	}

	/*
	 * Get names of the group nested User  - This return names of the users
	 */
	public List<String> getNamesOfNestedUsersOfGroup( String groupName, int startIndex, int maxResults) throws GroupNotFoundException, OperationFailedException, InvalidAuthenticationException, ApplicationPermissionException{
		List nestedGroupUsersName = conn.getNamesOfNestedUsersOfGroup(groupName, startIndex, maxResults);
		return nestedGroupUsersName;

	}

	/*
	 * Unnecessary method, might be needed. 
	 */

	public  GroupWithAttributes getGroupAttr (String grN) throws GroupNotFoundException, OperationFailedException, InvalidAuthenticationException, ApplicationPermissionException{
		GroupWithAttributes grp =  conn.getGroupWithAttributes(grN);
		System.out.println (grp.getName());
		return grp;
	}

	/*
	 * ----------------------------------IMPORTANT USER INFO----------------------
	 */

	public void getUserEmail (String userName) throws OperationFailedException, InvalidAuthenticationException, ApplicationPermissionException, InvalidEmailAddressException{
		conn.requestUsernames(userName);
	}

	/*
	 * Check if user is direct member of the group
	 * This can also use to check if user is a member of a group 
	 */
	public   boolean isUserDirectMemeber(String userName, String groupName) throws UserNotFoundException, OperationFailedException, ApplicationPermissionException, InvalidAuthenticationException, GroupNotFoundException{

		if(conn.getUser(userName).isActive() & conn.getGroup(groupName).isActive()){
			return conn.isUserDirectGroupMember(userName, groupName);
		}else {
			return false;
		}
	}

	/*
	 * check if user is a nested member. Not necessary feature from non admin point of view. 
	 */
	public  boolean isUserNestedGroupMember(String userName, String groupName) throws OperationFailedException, ApplicationPermissionException, InvalidAuthenticationException, UserNotFoundException, GroupNotFoundException{
		if(conn.getUser(userName).isActive() & conn.getGroup(groupName).isActive()){
			return conn.isUserNestedGroupMember(userName, groupName);
		}else {
			return false;
		}
	}

	/*
	 * --------------------------------------SEARCHES----------------------------
	 */

	/*
	 * search users and return user Entity which contains the search term.
	 */

	public  List searchUsers(String term) throws OperationFailedException, InvalidAuthenticationException, ApplicationPermissionException{

		TermRestriction sterm = new TermRestriction (UserTermKeys.USERNAME,MatchMode.CONTAINS, term); 
		SearchRestriction searchTerm = sterm;

		List<User> usersSearchResult = new ArrayList();

		usersSearchResult = conn.searchUsers(searchTerm, startIndex, maxResults);

		System.out.println(usersSearchResult.size());

		for(int i=0; i<usersSearchResult.size(); i++){
			User ue = usersSearchResult.get(i);
			//System.out.println( "USER NAME " +  ue.getName());
		}

		return usersSearchResult;

	}

	/*
	 * Search username names  and return username on the results  
	 */

	public  List<String>  searchUserNames(String searchUser) throws OperationFailedException, InvalidAuthenticationException, ApplicationPermissionException{
		TermRestriction sterm = new TermRestriction (UserTermKeys.USERNAME,MatchMode.CONTAINS, searchUser); 
		SearchRestriction searchTerm = sterm;

		List<String> userNameSearchResult = conn.searchUserNames(searchTerm, startIndex, maxResults);

		for(int i=0; i<userNameSearchResult.size(); i++){
			String ue = userNameSearchResult.get(i);
			System.out.println( "USER NAME " +  ue);
		}

		return userNameSearchResult;
	}

	/*
	 * Return user information including group information, user is active status, 
	 */
	public void searchUserInfo(String searchText) throws OperationFailedException, InvalidAuthenticationException, ApplicationPermissionException, UserNotFoundException {
		
		List  users= searchUsers(searchText); 
		
		
		for (int i = 0; i>users.size(); i++){
			User u = (User) users.get(i);
			
			List<String> grps = getGroupsForUser(u.getDisplayName()); 
			
			
			System.out.println(u.getDisplayName());
		}
		
		
		
	}

	public CrowdClient getClient() {
		return conn;
	}
	
}
